package sortingRMI_server;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import sortingRMI_client.ISorter;
import sortingRMI_client.PreSortChecker;

/*
 * note: borrowed much of this code from Lars Vogel
 * http://www.vogella.de/articles/JavaAlgorithmsQuicksort/article.html
 * 
 */

@SuppressWarnings("rawtypes")
public class Quicksort extends UnicastRemoteObject implements ISorter {

	private static final long serialVersionUID = -3672298891054795508L;

	protected Quicksort() throws RemoteException {
		super();
	}

	private PreSortChecker PreSort = new PreSortChecker();
	public int pivotCounter = 0;
	private Comparable[] sortList;
	
	@SuppressWarnings("static-access")
	public Comparable[] sort(Comparable[] arrayToBeSorted) throws RemoteException {
		
		
		// Check for empty or null array
		if (arrayToBeSorted == null || arrayToBeSorted.length == 0){
			throw new IllegalArgumentException("Array to be sorted must not be empty!\n");
		}
		
		// Check for pre-sorted array
		if (PreSort.checkSort(arrayToBeSorted)) {
			//System.out.println("Array is pre-sorted!\n");
			return arrayToBeSorted;
		}
		
		// Check for 1 element array
		if (arrayToBeSorted.length == 1) {
			return arrayToBeSorted;
		}
		
		sortList = arrayToBeSorted;
		quicksort(0, arrayToBeSorted.length - 1);
		
		return sortList;
		
	}

	@SuppressWarnings("unchecked")
	private void quicksort(int low, int high) {
		int lowArrayMarker = low;
		int highArrayMarker = high;
		
		// Get the pivot element from the middle of the list
		Comparable pivot = sortList[low + (high-low)/2];
		//pivotCounter++;
		//System.out.println("Pivot value is : " + pivot);

		// Divide into two lists
		while (lowArrayMarker <= highArrayMarker) {
			// If the current value from the left list is smaller then the pivot
			// element then get the next element from the left list
			while (sortList[lowArrayMarker].compareTo(pivot) < 0) {
				lowArrayMarker++;
			}
			// If the current value from the right list is larger then the pivot
			// element then get the next element from the right list
			while (sortList[highArrayMarker].compareTo(pivot) > 0 ) {
				highArrayMarker--;
			}

			// If we have found a arrayToBeSorted in the left list which is larger then
			// the pivot element and if we have found a value in the right list
			// which is smaller then the pivot element then we swap the
			// values.
			// As we are done we can increase i and j
			if (lowArrayMarker <= highArrayMarker) {
				swap(lowArrayMarker, highArrayMarker);
				lowArrayMarker++;
				highArrayMarker--;
			}
		}
		// Recursion
		if (low < highArrayMarker)
			quicksort(low, highArrayMarker);
		if (lowArrayMarker < high)
			quicksort(lowArrayMarker, high);
	}

	private void swap(int lowMarker, int highMarker) {
		Comparable temp = sortList[lowMarker];
		sortList[lowMarker] = sortList[highMarker];
		sortList[highMarker] = temp;
	}
}